﻿using System.Collections.Generic;
using System.Linq;
using MarriageFertility.Actions;
using MarriageFertility.Extensions;
using MarriageFertility.Helpers;
using MarriageFertility.Mcm;
using MarriageFertility.Notifications;
using MarriageFertility.Quests;
using MarriageFertility.Texts;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;
using TaleWorlds.Localization;

namespace MarriageFertility.Dialogs
{
    public static class MarriageDialog
    {
        public static CompetitionQuest CompetitionQuest;
        private static Hero _competitor;
        private static bool isMainDialog = false;

        public static void AddDialogs(CampaignGameStarter campaignGameStarter)
        {
            AddMarryDialogs(campaignGameStarter);
            AddPrisonDialogs(campaignGameStarter);
            AddCompetitionDialogs(campaignGameStarter);
            AddDivorceDialogs(campaignGameStarter);
        }

        private static void AddMarryDialogs(CampaignGameStarter campaignGameStarter)
        {
            campaignGameStarter.AddPlayerLine("common_marry_hero_request", "hero_main_options", "npc_marry_response",
                MarriageText.MarryRequestText.ToString(), CanMarry, null);

            campaignGameStarter.AddDialogLine("npc_marry_response_yes", "npc_marry_response", "hero_leave",
                MarriageText.MarryResponseYesText.ToString(), () => !HasCompetition() && AgreeMarry(),
                MarryCommonSpouse);

            campaignGameStarter.AddDialogLine("npc_marry_response_no", "npc_marry_response", "hero_main_options",
                MarriageText.MarryResponseNoText.ToString(), NotAgreeMarry, null);

            campaignGameStarter.AddPlayerLine("set_female_spouse_request", "hero_main_options",
                "set_main_hero_spouse_response",
                MarriageText.SetFemaleSpouseRequestText.ToString(), IsExFemaleSpouse, null);

            campaignGameStarter.AddPlayerLine("set_male_spouse_request", "hero_main_options",
                "set_main_hero_spouse_response",
                MarriageText.SetMaleSpouseRequestText.ToString(), IsExMaleSpouse, null);

            campaignGameStarter.AddDialogLine("set_main_hero_spouse", "set_main_hero_spouse_response",
                "hero_main_options",
                MarriageText.SetMainHeroSpouseResponseText.ToString(), null,
                () => RelationHelper.SetSpouse(Hero.OneToOneConversationHero));
        }

        private static void AddDivorceDialogs(CampaignGameStarter campaignGameStarter)
        {
            campaignGameStarter.AddPlayerLine("player_request_divorce", "hero_main_options", "lord_divorce_response",
                MarriageText.RequestDivorceText.ToString(), CanInitiateDivorce, null);

            campaignGameStarter.AddDialogLine("lord_ask_divorce_response", "lord_divorce_response",
                "player_confirm_divorce",
                MarriageText.AskPlayerAboutDivorceText.ToString(), null, null);

            campaignGameStarter.AddPlayerLine("player_confirm_divorce_yes", "player_confirm_divorce",
                "lord_final_divorce_yes",
                MarriageText.ConfirmDivorceYesText.ToString(), null, null);

            campaignGameStarter.AddPlayerLine("player_confirm_divorce_no", "player_confirm_divorce",
                "lord_final_divorce_no",
                MarriageText.ConfirmDivorceNoText.ToString(), null, null);

            campaignGameStarter.AddDialogLine("lord_final_divorce_yes", "lord_final_divorce_yes", "hero_main_options",
                MarriageText.LordAcceptsDivorceText.ToString(), null, EndDivorce);

            campaignGameStarter.AddDialogLine("lord_final_divorce_no", "lord_final_divorce_no", "hero_main_options",
                MarriageText.LordRejectsDivorceText.ToString(), null, null);
        }

        private static void AddPrisonDialogs(CampaignGameStarter campaignGameStarter)
        {
            campaignGameStarter.AddPlayerLine("mf_fetch_hero_start", "defeated_lord_answer", "fetch_lord_response",
                MarriageText.ChanceToLiveText.ToString(), () => MCMSettings.Instance.EnablePrisonMarryDialog, ()=> isMainDialog=false);

            campaignGameStarter.AddPlayerLine("mf_fetch_hero_main_hero", "hero_main_options", "fetch_lord_response",
                MarriageText.ChanceToLiveText.ToString(), ShowPrisonMainOptionDialog, ()=> isMainDialog=true);

            campaignGameStarter.AddDialogLine("mf_fetch_lord_response", "fetch_lord_response",
                "fetch_lord_choose",
                MarriageText.WhatChanceText.ToString(), null, null);

            campaignGameStarter.AddPlayerLine("mf_fetch_common_female", "fetch_lord_choose",
                "Spouse_response",
                MarriageText.BecomeMyWifeText.ToString(), IsFemale, null, 100, MarryCommonClickable);

            campaignGameStarter.AddPlayerLine("mf_fetch_common_male", "fetch_lord_choose",
                "Spouse_response",
                MarriageText.BecomeMyHusbandText.ToString(), IsMale, null, 100, MarryCommonClickable);

            campaignGameStarter.AddDialogLine("mf_fetch_Spouse_end", "Spouse_response",
                "close_window",
                MarriageText.WillingToBeWifeText.ToString(), null, MarryCommonSpouse);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_join_player", "fetch_lord_choose",
                "lord_join_player",
                MarriageText.JoinMyClanText.ToString(), null, null, 100, CanJoinClanClickable);

            campaignGameStarter.AddDialogLine("mf_lord_join_success", "lord_join_player",
                "close_window",
                MarriageText.WillingToBeSwordText.ToString(), CanJoinClan, JoinPlayerClan);

            campaignGameStarter.AddDialogLine("mf_lord_join_failed", "lord_join_player",
                "defeated_lord_answer",
                MarriageText.RefuseToSurrenderText.ToString(), CanNotJoinClan, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_spouse", "fetch_lord_choose",
                "lord_marry_spouse",
                MarriageText.MarryYourWifeText.ToString(), LordHasSpouse, null, 100, CanAgreeMarryHisSpouseClickable);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_spouse_success", "lord_marry_spouse",
                "close_window",
                MarriageText.AgreeMarrySpouseText.ToString(), CanAgreeMarryHisSpouse, MarryHisSpouse);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_spouse_failed", "lord_marry_spouse",
                "defeated_lord_answer",
                MarriageText.RefuseMarrySpouseText.ToString(), CanNotAgreeMarryHisSpouse, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_exspouse", "fetch_lord_choose",
                "lord_marry_exspouse",
                MarriageText.MarryYourExSpouseText.ToString(), LordHasExSpouse, null, 100, CanAgreeMarryHisExSpouseClickable);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_exspouse_success", "lord_marry_exspouse",
                "close_window",
                MarriageText.AgreeMarryExSpouseText.ToString(), CanAgreeMarryHisExSpouse, MarryHisExSpouse);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_spouse_failed", "lord_marry_exspouse",
                "defeated_lord_answer",
                MarriageText.VaseNotForBanditText.ToString(), CanNotAgreeMarryHisExSpouse, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_children", "fetch_lord_choose",
                "lord_marry_children",
                MarriageText.MarryLordDaughterRequestText.ToString(), LordHasFemaleChildren, null, 100, CanAgreeMarryHisChildrenClickable);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_children_success", "lord_marry_children",
                "close_window",
                MarriageText.MarryDaughterSuccessText.ToString(), CanAgreeMarryHisChildren, MarryHisChildren);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_spouse_failed", "lord_marry_children",
                "defeated_lord_answer",
                MarriageText.MarryDaughterFailText.ToString(), CanNotAgreeMarryHisChildren, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_mother", "fetch_lord_choose",
                "lord_marry_mother",
                MarriageText.MarryMotherRequestText.ToString(), LordHasMother, null, 100, CanAgreeMarryHisMotherClickable);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_mother_success", "lord_marry_mother",
                "close_window",
                MarriageText.MarryMotherSuccessText.ToString(), CanAgreeMarryHisMother, MarryHisMother);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_mother_failed", "lord_marry_mother",
                "defeated_lord_answer",
                MarriageText.MarryMotherFailedText.ToString(), CanNotAgreeMarryHisMother, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_elder_sister", "fetch_lord_choose",
                "lord_marry_elder_sister",
                MarriageText.AskMarryElderSisterText.ToString(), LordHasElderSister, null, 100, CanAgreeMarryHisElderSisterClickable);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_elder_sister_success", "lord_marry_elder_sister",
                "close_window",
                MarriageText.MarryElderSisterSuccessText.ToString(), CanAgreeMarryHisElderSister, MarryHisElderSister);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_elder_sister_failed", "lord_marry_elder_sister",
                "defeated_lord_answer",
                MarriageText.MarryElderSisterFailedText.ToString(), CanNotAgreeMarryHisElderSister, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_litter_sister", "fetch_lord_choose",
                "lord_marry_litter_sister",
                MarriageText.AskMarryLitterSisterText.ToString(), LordHasLitterSister, null, 100, CanAgreeMarryHisLitterSisterClickable);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_litter_sister_success", "lord_marry_litter_sister",
                "close_window",
                MarriageText.MarryLitterSisterSuccessText.ToString(), CanAgreeMarryHisLitterSister,
                MarryHisLitterSister);

            campaignGameStarter.AddDialogLine("mf_lord_lord_marry_litter_sister_failed", "lord_marry_litter_sister",
                "defeated_lord_answer",
                MarriageText.MarryProposalRejectedText.ToString(), CanNotAgreeMarryHisLitterSister, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_marry_clan", "fetch_lord_choose",
                "lord_marry_clan_member",
                MarriageText.AskMarryClanMemberText.ToString(), PlayerHaveClanMember, null);

            campaignGameStarter.AddPlayerLine("mf_ask_lord_join_other_clan", "fetch_lord_choose",
                "lord_join_other_clan",
                MarriageText.AskJoinOtherClanText.ToString(), LordCanJoinOtherClan, null, 100, RelationToJoinOtherClanClickable);

            campaignGameStarter.AddDialogLine("mf_lord_join_other_clan_agree", "lord_join_other_clan", "close_window",
                MarriageText.AgreeJoinOtherClanText.ToString(),
                AgreeToJoinOtherClan, null);

            campaignGameStarter.AddDialogLine("mf_lord_join_other_clan_deny", "lord_join_other_clan",
                "defeated_lord_answer", MarriageText.DenyJoinOtherClanText.ToString(),
                DenyToJoinOtherClan, null);

            campaignGameStarter.AddDialogLine("mf_lord_ask_marry_who", "lord_marry_clan_member",
                "close_window",
                MarriageText.WhoToMarryQuestionText.ToString(), null, ShowHeroSelectionInquiry);

            campaignGameStarter.AddPlayerLine("mf_ask_show_equipment", "fetch_lord_choose", "lord_show_equipment",
                MarriageText.AskShowEquipmentText.ToString(), null, null);

            campaignGameStarter.AddDialogLine("mf_lord_show_equipment_success", "lord_show_equipment", "close_window",
                MarriageText.ShowEquipmentResponseText.ToString(), null, ShowEquipmentAction);

            campaignGameStarter.AddPlayerLine("mf_ask_be_good", "fetch_lord_choose", "lord_be_good",
                MarriageText.AskBeGoodText.ToString(), null, null);

            campaignGameStarter.AddDialogLine("mf_lord_be_good_success", "lord_be_good", "hero_leave",
                MarriageText.BeGoodResponseText.ToString(), null, ReleaseLord);

            campaignGameStarter.AddPlayerLine("mf_ask_pay_ransom", "fetch_lord_choose", "lord_pay_ransom",
                MarriageText.AskPayRansomText.ToString(), null, null);

            campaignGameStarter.AddDialogLine("mf_lord_pay_ransom_success", "lord_pay_ransom", "hero_leave",
                MarriageText.PayRansomResponseText.ToString(), null, TakeRansomAndRelease);

            campaignGameStarter.AddPlayerLine("mf_ask_entertain_me1", "fetch_lord_choose", "lord_entertain_response",
                MarriageText.AskEntertainMeText.ToString(),
                () => Hero.OneToOneConversationHero != null &&
                      (MCMSettings.Instance.EnableSameGender ||
                       Hero.OneToOneConversationHero.IsFemale != Hero.MainHero.IsFemale),
                null);

            campaignGameStarter.AddPlayerLine("mf_ask_entertain_me2", "hero_main_options", "lord_entertain_response",
                MarriageText.AskEntertainMeText.ToString(),
                () => ShowPrisonMainOptionDialog() && Hero.OneToOneConversationHero != null &&
                      (MCMSettings.Instance.EnableSameGender ||
                       Hero.OneToOneConversationHero.IsFemale != Hero.MainHero.IsFemale),
                null);

            campaignGameStarter.AddDialogLine("mf_lord_entertain_response", "lord_entertain_response", "hero_leave",
                MarriageText.EntertainResponseText.ToString(), null, EntertainAndRelease);

            campaignGameStarter.AddPlayerLine("mf_return_last_menu", "fetch_lord_choose",
                "return_last_npc_response",
                MarriageText.NothingToSayText.ToString(), null, null);

            campaignGameStarter.AddDialogLine("mf_return_last_npc1", "return_last_npc_response",
                "defeated_lord_answer",
                MarriageText.DoNotWasteMyTimeText.ToString(), ()=> !isMainDialog, null);
            
            campaignGameStarter.AddDialogLine("mf_return_last_npc2", "return_last_npc_response",
                "hero_main_options",
                MarriageText.DoNotWasteMyTimeText.ToString(), ()=> isMainDialog, null);
        }
        
        


        private static void AddCompetitionDialogs(CampaignGameStarter campaignGameStarter)
        {
            campaignGameStarter.AddDialogLine("npc_mention_competitor", "npc_marry_response",
                "hero_competitor_reaction",
                QuestText.NpcMentionCompetitor.ToString(),
                CompetitionDialogCondition, null);

            campaignGameStarter.AddPlayerLine("react_to_male_competitor", "hero_competitor_reaction",
                "hero_competitor_challenge",
                QuestText.ReactToMaleCompetitor.ToString(),
                IsMaleCompetition, null);

            campaignGameStarter.AddPlayerLine("react_to_female_competitor", "hero_competitor_reaction",
                "hero_competitor_challenge",
                QuestText.ReactToFemaleCompetitor.ToString(),
                IsFeMaleCompetition, null);

            campaignGameStarter.AddPlayerLine("react_to_reject_competitor", "hero_competitor_reaction",
                "hero_leave",
                QuestText.ReactToRejectCompetitor.ToString(),
                null, null);

            campaignGameStarter.AddDialogLine("npc_competitor_challenge_response", "hero_competitor_challenge",
                "hero_duel_decision", "{=!}{RESPONSE_STRING}", CompetitionInfo, null);

            campaignGameStarter.AddPlayerLine("npc_competitor_challenge_decide", "hero_duel_decision",
                "hero_leave", QuestText.NpcCompetitorChallengeDecide.ToString(), null, StartCompetitionQuest);
        }

        private static void MarryHero(Hero marryHero, Hero defeatedHero)
        {
            ChangeRelationAction.ApplyRelationChangeBetweenHeroes(defeatedHero, marryHero, -10);
            ChangeRelationAction.ApplyRelationChangeBetweenHeroes(Hero.MainHero, marryHero, 50);
            ChangeRelationAction.ApplyRelationChangeBetweenHeroes(Hero.MainHero, defeatedHero, -10);
            Hero.MainHero.ForceMarry(marryHero);
        }

        private static void MarryHisSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null && hero.Spouse != null && hero.Spouse.IsFemale && hero.Spouse.IsAlive)
            {
                MarryHero(hero.Spouse, hero);
            }
        }

        private static bool CanMarry()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && (MCMSettings.Instance.EnableSameGender || Hero.MainHero.IsFemale != hero.IsFemale) &&
                   !Hero.MainHero.IsSpouse(hero) && (hero.IsLord || hero.IsWanderer);
        }

        private static bool CompetitionDialogCondition()
        {
            bool questStats = CompetitionQuest == null || CompetitionQuest.IsFinalized;
            return MCMSettings.Instance.EnableCompetitionQuest && questStats && HasCompetition() && AgreeMarry();
        }


        private static bool HasCompetition()
        {
            CompetitionQuest = null;
            Hero hero = Hero.OneToOneConversationHero;
            bool questStats = CompetitionQuest == null || CompetitionQuest.IsFinalized;
            _competitor = hero.HighestRelationSuitor();
            return MCMSettings.Instance.EnableCompetitionQuest && hero != null && questStats && _competitor != null;
        }

        private static bool IsMaleCompetition()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && !_competitor.IsFemale;
        }

        private static bool IsFeMaleCompetition()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && _competitor.IsFemale;
        }

        private static bool CompetitionInfo()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null && _competitor != null)
            {
                TextObject genderSpecificInfo = _competitor.IsFemale
                    ? MarriageText.CompetitorFeMaleInfo
                    : MarriageText.CompetitorMaleInfo;
                MBTextManager.SetTextVariable("RESPONSE_STRING",
                    genderSpecificInfo.SetTextVariable("heroName", _competitor.Name));
                return true;
            }

            return false;
        }


        private static void StartCompetitionQuest()
        {
            Hero hero = Hero.OneToOneConversationHero;
            Hero competitor = hero?.HighestRelationSuitor();
            if (hero != null && competitor != null)
            {
                CompetitionQuest =
                    new CompetitionQuest("CompetitionDuelQuest", hero, competitor,
                        CampaignTime.Now + CampaignTime.Days(30f));
                CompetitionQuest.StartQuest();
            }
        }

        private static bool AgreeMarry()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.GetRelationWithPlayer() > 50;
        }

        private static bool NotAgreeMarry() => !AgreeMarry();

        private static void MarryHisExSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null && hero.ExSpouses.Count(h => h.IsFemale && h.IsAlive) > 0)
            {
                Hero exSpouse = hero.ExSpouses.First(h => h.IsFemale && h.IsAlive);
                MarryHero(exSpouse, hero);
            }
        }

        private static void MarryHisChildren()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null && hero.Children.Count(h => h.IsFemale && h.IsAlive) > 0)
            {
                Hero children = hero.Children.First(h => h.IsFemale && h.IsAlive && h.Age >= 18);
                MarryHero(children, hero);
            }
        }

        private static void MarryHisMother()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null && hero.Mother != null && hero.Mother.IsAlive)
            {
                MarryHero(hero.Mother, hero);
            }
        }

        private static void MarryHisElderSister()
        {
            Hero hero = Hero.OneToOneConversationHero;
            Hero femaleHero = hero.ElderSister();
            if (femaleHero != null)
            {
                MarryHero(femaleHero, hero);
            }
        }

        private static void MarryHisLitterSister()
        {
            Hero hero = Hero.OneToOneConversationHero;
            Hero femaleHero = hero.LittleSister();
            if (femaleHero != null)
            {
                MarryHero(femaleHero, hero);
            }
        }

        private static bool ShowPrisonMainOptionDialog()
        {
            if (Hero.OneToOneConversationHero == null || !MCMSettings.Instance.EnablePrisonMarryDialog)
            {
                return false;
            }

            var mainParty = MobileParty.MainParty;
            if (mainParty?.PrisonRoster == null)
            {
                return false;
            }

            var prisonerCount = mainParty.PrisonRoster.GetElementNumber(Hero.OneToOneConversationHero.CharacterObject);
            return prisonerCount > 0;
        }
        
        private static bool MarryCommonClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null)
            {
                explanation = MarriageText.NoHeroAvailableText;
                return false;
            }

            if (hero.GetRelationWithPlayer() <= 50)
            {
                explanation = MarriageText.Require50AffectionToMarryText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            explanation = MarriageText.WillingToMarryText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }

        private static bool CanAgreeMarryHisSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.Spouse != null && hero.Spouse.IsFemale && hero.Spouse.IsAlive &&
                   hero.GetRelation(hero.Spouse) < -20 &&
                   hero.GetRelationWithPlayer() >= 70 &&
                   hero.Clan?.Kingdom == null;
        }
        
        private static bool CanAgreeMarryHisSpouseClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null || hero.Spouse == null || !hero.Spouse.IsFemale || !hero.Spouse.IsAlive)
            {
                explanation = MarriageText.NoEligibleSpouseText;
                return false;
            }

            if (hero.GetRelation(hero.Spouse) >= -20)
            {
                explanation = MarriageText.SpouseRelationBelowNegative20Text;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 70)
            {
                explanation = MarriageText.Require70AffectionForSpouseText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            if (hero.Clan?.Kingdom != null)
            {
                explanation = MarriageText.ClanNotInKingdomText;
                return false;
            }

            explanation = MarriageText.CanMarrySpouseText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }
        

        private static bool CanNotAgreeMarryHisSpouse() => !CanAgreeMarryHisSpouse();

        private static bool CanAgreeMarryHisExSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null || hero.ExSpouses.Count(h => h.IsFemale && h.IsAlive) <= 0) return false;
            Hero exSpouse = hero.ExSpouses.First(h => h.IsFemale && h.IsAlive);
            return hero.GetRelation(exSpouse) < -20 && hero.GetRelationWithPlayer() >= 50 &&
                   hero.Clan?.Kingdom == null;
        }
        
        private static bool CanAgreeMarryHisExSpouseClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null || hero.ExSpouses.Count(h => h.IsFemale && h.IsAlive) <= 0)
            {
                explanation = MarriageText.NoEligibleExSpouseText;
                return false;
            }

            Hero exSpouse = hero.ExSpouses.First(h => h.IsFemale && h.IsAlive);
            if (hero.GetRelation(exSpouse) >= -20)
            {
                explanation = MarriageText.ExSpouseRelationBelowNegative20Text;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 50)
            {
                explanation = MarriageText.Require50AffectionForExSpouseText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            if (hero.Clan?.Kingdom != null)
            {
                explanation = MarriageText.ClanNotInKingdomText;
                return false;
            }
            explanation = MarriageText.CanMarryExSpouseText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }

        private static bool CanNotAgreeMarryHisExSpouse() => !CanAgreeMarryHisExSpouse();

        private static bool CanAgreeMarryHisChildren()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null || hero.Children.Count(h => h.IsFemale && h.IsAlive && h.Age >= 18) <= 0) return false;
            Hero children = hero.Children.First(h => h.IsFemale && h.IsAlive && h.Age >= 18);
            return hero.GetRelation(children) < 30 && hero.GetRelationWithPlayer() >= 80 &&
                   hero.Clan?.Kingdom == null;
        }

        private static bool CanAgreeMarryHisChildrenClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null || hero.Children.Count(h => h.IsFemale && h.IsAlive && h.Age >= 18) <= 0)
            {
                explanation = MarriageText.NoEligibleDaughtersText;
                return false;
            }

            Hero children = hero.Children.First(h => h.IsFemale && h.IsAlive && h.Age >= 18);
            if (hero.GetRelation(children) >= 30)
            {
                explanation = MarriageText.DaughterRelationBelow30Text;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 80)
            {
                explanation = MarriageText.Require80AffectionForDaughterText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            if (hero.Clan?.Kingdom != null)
            {
                explanation = MarriageText.ClanNotInKingdomText;
                return false;
            }

            explanation = MarriageText.CanMarryDaughterText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }
        
        private static bool CanNotAgreeMarryHisChildren() => !CanAgreeMarryHisChildren();

        private static bool CanAgreeMarryHisMother()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return LordHasMother() && hero.GetRelationWithPlayer() >= 90;
        }
        
        private static bool CanAgreeMarryHisMotherClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (!LordHasMother())
            {
                explanation = MarriageText.NoLivingMotherText;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 90)
            {
                explanation = MarriageText.Require90AffectionForMotherText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            explanation = MarriageText.CanMarryMotherText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }

        private static bool CanNotAgreeMarryHisMother() => !CanAgreeMarryHisMother();

        private static bool CanAgreeMarryHisElderSister()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return LordHasElderSister() && hero.GetRelationWithPlayer() >= 60;
        }

        private static bool CanAgreeMarryHisElderSisterClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (!LordHasElderSister())
            {
                explanation = MarriageText.NoEligibleElderSisterText;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 60)
            {
                explanation = MarriageText.Require60AffectionForElderSisterText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            explanation = MarriageText.CanMarryElderSisterText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }

        private static bool CanNotAgreeMarryHisElderSister() => !CanAgreeMarryHisElderSister();


        private static bool CanAgreeMarryHisLitterSister()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return LordHasLitterSister() && hero.GetRelationWithPlayer() >= 60;
        }
        private static bool CanAgreeMarryHisLitterSisterClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (!LordHasLitterSister())
            {
                explanation = MarriageText.NoEligibleYoungerSisterText;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 60)
            {
                explanation = MarriageText.Require60AffectionForYoungerSisterText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            explanation = MarriageText.CanMarryYoungerSisterText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }
        private static bool CanNotAgreeMarryHisLitterSister() => !CanAgreeMarryHisLitterSister();


        private static bool IsFemale()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.IsFemale &&
                   (MCMSettings.Instance.EnableSameGender || hero.IsFemale != Hero.MainHero.IsFemale);
        }

        private static bool IsMale()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && !hero.IsFemale &&
                   (MCMSettings.Instance.EnableSameGender || hero.IsFemale != Hero.MainHero.IsFemale);
        }

        private static bool LordHasSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.Spouse != null && hero.Spouse.IsFemale && hero.Spouse.IsAlive;
        }


        private static bool LordHasExSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.ExSpouses.Count(h => h.IsFemale && h.IsAlive) > 0;
        }

        private static bool LordHasFemaleChildren()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.Children.Count(c => c.IsFemale && c.IsAlive && c.Age >= 18) > 0;
        }

        private static bool LordHasMother()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.Mother != null && hero.Mother.IsAlive;
        }

        private static bool LordHasElderSister()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && !Hero.MainHero.IsFemale && hero.Mother != null &&
                   hero.Mother.Children.Count(h => h.IsFemale && h.Age > hero.Age && h.IsAlive) > 0;
        }

        private static bool LordHasLitterSister()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && !Hero.MainHero.IsFemale && hero.Mother != null &&
                   hero.Mother.Children.Count(h => h.IsFemale && h.Age < hero.Age && h.IsAlive) > 0;
        }

        private static bool PlayerHaveClanMember()
        {
            Hero hero = Hero.OneToOneConversationHero;
            bool hasClanMember =
                Hero.MainHero.Clan.Heroes.Count(h =>
                    (MCMSettings.Instance.EnableSameGender || h.IsFemale != hero.IsFemale) && h.IsAlive &&
                    h != Hero.MainHero) > 0;
            return hero != null && hasClanMember;
        }

        private static bool LordCanJoinOtherClan()
        {
            Hero hero = Hero.OneToOneConversationHero;
            Kingdom kingdom = Clan.PlayerClan.Kingdom;
            if (hero == null || kingdom == null) return false;
            return kingdom.Clans.Count(c => c != Clan.PlayerClan) > 0;
        }

        private static bool RelationToJoinOtherClan()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.GetRelationWithPlayer() >= 30;
        }
        
        private static bool RelationToJoinOtherClanClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null)
            {
                explanation = MarriageText.NoHeroAvailableText;
                return false;
            }

            if (hero.GetRelationWithPlayer() < 30)
            {
                explanation = MarriageText.Require30AffectionForOtherClanText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            explanation = MarriageText.WillingToJoinOtherClanText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }

        private static bool AgreeToJoinOtherClan()
        {
            if (RelationToJoinOtherClan())
            {
                var clanElements = GetInquiryElements(Clan.PlayerClan.Kingdom);
                MBInformationManager.ShowMultiSelectionInquiry(
                    new MultiSelectionInquiryData(
                        ClanText.ClanSelection, // 对话框标题
                        ClanText.SelectClanToJoin, // 对话框描述
                        clanElements, // 获取可加入的国家列表
                        true,
                        1, 1,
                        CommonText.Confirm, // 确认按钮文本
                        CommonText.Cancel, // 取消按钮文本
                        LordJoinOtherClan, // 确认后的回调函数
                        null // 取消后的回调函数
                    ),
                    true
                );
                return true;
            }

            return false;
        }

        private static bool DenyToJoinOtherClan() => !RelationToJoinOtherClan();

        private static void ShowHeroSelectionInquiry()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                List<InquiryElement> inquiryElements = GetInquiryElements(hero);
                MBInformationManager.ShowMultiSelectionInquiry(
                    new MultiSelectionInquiryData(
                        MarriageText.MarriageMemberSelection.ToString(),
                        MarriageText.SelectMarriageCandidates.ToString(),
                        inquiryElements, true, 1, 1,
                        CommonText.Confirm, CommonText.Cancel,
                        MarryToHero, null), true);
            }
        }

        private static List<InquiryElement> GetInquiryElements(Hero hero)
        {
            List<InquiryElement> elements = new List<InquiryElement>();
            foreach (var clanMember in Hero.MainHero.Clan.Heroes)
            {
                if (!clanMember.IsPlayer() && clanMember.IsAlive &&
                    (MCMSettings.Instance.EnableSameGender || clanMember.IsFemale != hero.IsFemale))
                {
                    elements.Add(new InquiryElement(clanMember, clanMember.Name.ToString(),
                        new ImageIdentifier(CharacterCode.CreateFrom(clanMember.CharacterObject))));
                }
            }

            return elements;
        }


        private static List<InquiryElement> GetInquiryElements(Kingdom kingdom)
        {
            List<InquiryElement> elements = new List<InquiryElement>();
            if (kingdom == null || kingdom.Clans.Count <= 0) return elements;
            foreach (var clan in kingdom.Clans)
            {
                if (clan != Clan.PlayerClan)
                {
                    elements.Add(new InquiryElement(clan, clan.Name.ToString(),
                        new ImageIdentifier(clan.Banner)));
                }
            }

            return elements;
        }

        private static void MarryToHero(List<InquiryElement> elements)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                Hero member = elements.First().Identifier as Hero;
                member.ForceMarry(hero);
            }
        }

        private static bool CanJoinClan()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.GetRelation(Hero.MainHero) >= 30;
        }
        
        private static bool CanJoinClanClickable(out TextObject explanation)
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero == null)
            {
                explanation = MarriageText.NoHeroAvailableText;
                return false;
            }

            if (hero.GetRelation(Hero.MainHero) < 30)
            {
                explanation = MarriageText.Require30AffectionForClanText.SetTextVariable("HERO_NAME", hero.Name);
                return false;
            }

            explanation = MarriageText.WillingToJoinClanText.SetTextVariable("HERO_NAME", hero.Name);
            return true;
        }
        
        private static bool CanNotJoinClan() => !CanJoinClan();

        private static void MarryCommonSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                if (hero.IsWanderer && hero.CompanionOf == null)
                {
                    AddCompanionAction.Apply(Clan.PlayerClan, Hero.OneToOneConversationHero);
                }
                Hero.MainHero.ForceMarry(hero);
            }
        }

        private static void JoinPlayerClan()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                ClanHelper.LordJoinPlayerClan(hero);
                CustomerMarriageAction.ChangePrisonerToParty(hero);
                if (PartyBase.MainParty?.PrisonRoster?.GetTroopCount(hero.CharacterObject) > 0)
                {
                    PartyBase.MainParty?.PrisonRoster.AddToCounts(hero.CharacterObject, -1);
                }
            }
        }

        private static void LordJoinOtherClan(List<InquiryElement> elements)
        {
            Clan clan = elements.Select(e => e.Identifier).OfType<Clan>().FirstOrDefault();
            Hero hero = Hero.OneToOneConversationHero;
            if (clan == null || hero == null) return;
            hero.Clan.Heroes?.Remove(hero);
            hero.Clan = clan;
        }

        private static bool IsExFemaleSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && hero.IsFemale && Hero.MainHero.ExSpouses.Contains(hero);
        }

        private static bool IsExMaleSpouse()
        {
            Hero hero = Hero.OneToOneConversationHero;
            return hero != null && !hero.IsFemale && Hero.MainHero.ExSpouses.Contains(hero);
        }

        private static bool CanInitiateDivorce()
        {
            return Hero.OneToOneConversationHero != null && Hero.MainHero.IsSpouse(Hero.OneToOneConversationHero);
        }

        private static void EndDivorce()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                DivorceAction.Apply(Hero.MainHero, hero);
                ChangeRelationAction.ApplyPlayerRelation(hero, -50);
            }
        }

        private static void ShowEquipmentAction()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                for (int i = 0; i < 12; i++)
                {
                    ItemObject itemObject = hero.BattleEquipment[i].Item;
                    if (itemObject != null)
                    {
                        PartyBase.MainParty.ItemRoster.AddToCounts(itemObject, 1);
                        hero.BattleEquipment[i] = new EquipmentElement();
                    }
                }

                Log.CommonMessage(MarriageText.EquipmentGainedText.SetTextVariable("HERO_NAME", hero.Name));
                EndCaptivityAction.ApplyByReleasedAfterBattle(hero);
            }
        }

        private static void ReleaseLord()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                ChangeRelationAction.ApplyPlayerRelation(hero, 10);
                foreach (var trait in Helper.RelevantTraits)
                {
                    if (hero.GetTraitLevel(trait) < 0)
                    {
                        hero.SetTraitLevel(trait, 0);
                        break;
                    }
                }

                EndCaptivityAction.ApplyByReleasedAfterBattle(hero);
            }
        }

        private static void EntertainAndRelease()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                hero.TryPregnancy();
                ChangeRelationAction.ApplyPlayerRelation(hero, 5);
                if (hero.Spouse != null && hero.Spouse != Hero.MainHero)
                {
                    ChangeRelationAction.ApplyRelationChangeBetweenHeroes(hero.Spouse, hero,-25);
                }
                if (RelationHelper.HotButterFound)
                {
                    MBInformationManager.ShowSceneNotification(new HotButterNotification(Hero.MainHero, hero,
                        hero.CurrentSettlement, null));
                }
                else
                {
                    Log.CommonMessage(SexFriendText.GentleIntimacyDescriptionText, TextColor.Pink);
                }
                EndCaptivityAction.ApplyByReleasedAfterBattle(hero);
            }
        }

        private static void TakeRansomAndRelease()
        {
            Hero hero = Hero.OneToOneConversationHero;
            if (hero != null)
            {
                int gold = hero.Gold;
                if (gold > 0)
                {
                    float giveGold = gold * 0.1f;
                    GiveGoldAction.ApplyBetweenCharacters(hero, Hero.MainHero, (int)giveGold);
                    EndCaptivityAction.ApplyByReleasedAfterBattle(hero);
                }
            }
        }
    }
}